The dir tree is :
Init project with npm init
npm init [-y]
install koa with ==install==
npm install koa koa-convert koa-router koa-static koa-views -S
using the npm package named config (website)
npm install config -S
安裝完建立 default.js,此處與底下的官方教學不同,這邊使用 js 模組的方式,不過基本上與下方 JSON 方式相同,模組釋出的也是一個 JS Object
module.exports = {
    'service': {
        'name': 'React',
        'external_url': 'http://localhost:3001'
    },
    'server': {
        'port': 3001
    }
}
Open the app.js in root dir and coding using the code above
此工具可以幫助你把所有的相關設定都整理到同一個檔案中,下是官方的教學內容
install it
$ npm install config
create a folder to locate the config file
$ mkdir config
Edit the file named ==default,json==
$ vim config/default.json
The file look like:
{
  // Customer module configs
  "Customer": {
    "dbConfig": {
      "host": "localhost",
      "port": 5984,
      "dbName": "customers"
    },
    "credit": {
      "initialLimit": 100,
      // Set low for development
      "initialDays": 1
    }
  }
}
Use configs in your code
var config = require('config');
//...
var dbConfig = config.get('Customer.dbConfig');
db.connect(dbConfig, ...);
直接使用第二步驟安裝的 ==koa-router== 來設定首頁的路徑,直接使用 GET 來渲染
const Koa = require('koa');
const convert = require('koa-convert');
const serve = require('koa-static');
const path = require('path');
const config = require('config');
const app = new Koa();
app.use(convert(serve(path.join(__dirname, 'public'))));
app.use( ctx => {
    ctx.body = 'Hello World'
})
app.listen(config.server.port, _=>{
    console.log(`server starting on ${config.server.port}`)
})
接著使用 kuo 中的 Router 來控制 koa 應用的路由 (與 express router 類似,可用 async)
const Koa = require('koa');
const convert = require('koa-convert');
const serve = require('koa-static');
const Router = require('koa-router');
const path = require('path');
const config = require('config');
const app = new Koa();
const router = new Router();
app.use(convert(serve(path.join(__dirname, 'public'))));
router.get('/', async (ctx, next) => {
    ctx.body = 'Hello world';
});
app.use(router.routes());
app.listen(config.server.port, _=>{
    console.log(`server starting on ${config.server.port}`)
})
安裝 Pug 套件,此套件是模板引擎 Jade 的前身,可用 ejs 代替(與 koa 的配合可以再實驗)
$ npm install pug -S
在 views 新增 layout.pug 檔案並利用 CDN 引入 JQiery, Semantic UI
doctype html
html
    head
        meta(http-equiv='content-type', content='text/html')
        meta(name='viewport', content='width=device-width, initial-scale=1.0')
        meta(http-equiv='X-UA-Compatible', content='IE=edge')
        title LandingPage
        link(href='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.9/semantic.min.css', mefia='all', rel='stylesheet', type='text/css')
        script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js')
        script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.9/semantic.min.js')
        block head
    body
        block body
在 views 中在建立一個 index.pug
extends layout
block body
    h1 Hello Pug!!
在 app.js 中使用 koa-views 並且將 pug 的內容渲染到前端
const views = require('koa-views');
//Render Pug
app.use(views(path.join(__dirname, 'views'), {extension: 'pug'}));
router.get('/', async (ctx, next) => {
    await ctx.render('index');
});
直得注意的是這邊的渲染利用到 await 的方法等待上一個 middleware 做完後做渲染,達到同步執行的效果。
使用 webpack2 建置好 React 的開發環境,安裝建置環境相關的工具
$ npm install babel-polyfill babel-cli babel-core babel-loader babel-preset-es2017 babel-preset-react babel-preset-stage-0 react react-dom webpack -S
在根目錄新增 web pack.config.js 並且設定其內容
var path = require('path')
var webpack = require('webpack')
module.exports - {
    context: path.join(__dirname, 'src'),
    entry: {
        bundle: './app.jsx',
        vendors: [
            'bable-polyfill',
            'react',
            'react-dom'
        ]
    },
    output: {
        filename: '[name].js',
        publishPath: '/assets/',
        path: path.join(__dirname, 'public', 'assets')
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                enforce: 'pre',
                loader: 'babel-loader',
                options: {
                    pressets : [ 'react', 'es2017', 'stage-0' ]
                }
            }
        ],
        plugin: [
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendors'     //Specify the common bundle's name
            })
        ],
        externals: {
            config: JSON.stringify(require('config'))
        },
        resolve: {
            extensions: ['.js', '.jsx'],
            alias: {
                'react$': 'react/dist/react.min.js',
                'react-dom$': 'react-dom/dist/react-dom.min.js'
            }
        }
    }
}
使用局部的 webpack 打包
$ ./node_modules/.bin/webpack
以上會有錯誤,解決中,目前應該要確定 webpack 的版本是 2.3.2
錯誤如下:
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration.module has an unknown property 'resolve'. These properties are valid:
   object { exprContextCritical?, exprContextRecursive?, exprContextRegExp?, exprContextRequest?, loaders?, noParse?, rules?, unknownContextCritical?, unknownContextRecursive?, unknownContextRegExp?, unknownContextRequest?, unsafeCache?, wrappedContextCritical?, wrappedContextRecursive?, wrappedContextRegExp?, strictExportPresence? }
   Options affecting the normal modules (`NormalModuleFactory`).
 - configuration.output has an unknown property 'publishPath'. These properties are valid:
   object { auxiliaryComment?, chunkFilename?, crossOriginLoading?, devtoolFallbackModuleFilenameTemplate?, devtoolLineToLine?,devtoolModuleFilenameTemplate?, filename?, hashDigest?, hashDigestLength?, hashFunction?, hotUpdateChunkFilename?, hotUpdateFunction?, hotUpdateMainFilename?, jsonpFunction?, library?, libraryTarget?, path?, pathinfo?, publicPath?, sourceMapFilename?, sourcePrefix?, strictModuleExceptionHandling?, umdNamedDefine? }
   Options affecting the output of the compilation. `output` options tell webpack how to write the compiled files to disk.